/**
 * FileName: DeviceServiceImpl
 * Author: Wb
 * Date: 2025/9/24 9:59
 * Description:
 * History:
 */
package org.test.device.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.test.device.config.mqtt.MqttReceiver;
import org.test.device.constant.AttributesValue;
import org.test.device.constant.DeviceStatusEnum;
import org.test.device.enty.Device;
import org.test.device.enty.Product;
import org.test.device.enty.ProductProperty;
import org.test.device.mapper.DeviceMapper;
import org.test.device.mapper.ProductMapper;
import org.test.device.mapper.ProductPropertyMapper;
import org.test.device.params.QueryDeviceParam;
import org.test.device.params.SaveDeviceParam;
import org.test.device.params.UpdateDeviceParam;
import org.test.device.service.DeviceService;
import org.test.device.service.MqttAuthService;
import org.test.device.service.MqttService;
import org.test.device.utils.BusinessCode;
import org.test.device.utils.ResultData;
import org.test.device.utils.SqlTypeConverter;
import org.test.device.architecture.exception.BusinessException;
import org.test.device.vo.device.DeviceReceiveInfo;
import org.test.device.vo.device.DeviceVoList;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author Wb
 * @create 2025/9/24
 * @since 1.0.0
 */
@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    DeviceMapper deviceMapper;

    @Autowired
    ProductMapper productMapper;

    @Autowired
    MqttAuthService mqttAuthService;

    @Autowired
    ProductPropertyMapper productPropertyMapper;

    @Autowired
    MqttReceiver mqttReceiver;

    @Autowired
    MqttService mqttService;

    @Autowired(required = false)
    private SimpMessagingTemplate webSocketTemplate;

    /**
    * @Author Mr.Wang
    * @Description 查询设备列表
    * @Date 10:26 2025/9/29
    * @param param 查询参数
    **/
    @Override
    public List<DeviceVoList> getDeviceList(QueryDeviceParam param) {
        LambdaQueryWrapper<Device> deviceWrapper=new LambdaQueryWrapper<>();
        deviceWrapper.eq(Device::getDeleted,AttributesValue.NOT_DELETED);
        Optional.ofNullable(param.getStatus())
                        .filter(Objects::nonNull)
                        .ifPresent(s->deviceWrapper.eq(Device::getStatus,s));
        Optional.ofNullable(param.getSearchKey())
                .filter(key -> !key.isEmpty())
                .ifPresent(k -> deviceWrapper.and(wrapper -> wrapper
                        .like(Device::getCode, k)
                        .or()
                        .like(Device::getName, k)
                        .or()
                        .like(Device::getAuthMethod, k)
                        .or()
                        .like(Device::getAccessMethod, k)));

        return deviceMapper.selectList(deviceWrapper).stream()
                .map(list -> {
                    DeviceVoList vo = new DeviceVoList();
                    SqlTypeConverter.convertEntity(list, vo, "yyyy-mm-dd HH:mm:ss");
                    vo.setStatus(Objects.requireNonNull(DeviceStatusEnum.getByCode(list.getStatus())).getDesc());
                    Product product = productMapper.selectById(vo.getProductId());
                    vo.setProductName(product.getName());
                    vo.setProductCode(product.getCode());
                    return vo;
                })
                .peek(vo -> log.info("转换后的设备信息: {}", JSON.toJSONString(vo)))
                .collect(Collectors.toList());
    }

    /**
    * @Author Mr.Wang
    * @Description 新增设备信息
    * @Date 16:10 2025/9/28
    * @param param 新增数据集
    **/
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void saveDevice(SaveDeviceParam param) {
        try {
            Device device=new Device();
            SqlTypeConverter.copyEntity(param,device);
            device.setStatus(AttributesValue.DEVICE_STATUS_UNAUTHENTICATED.getCode());
            deviceMapper.insert(device);
            log.info("添加成功！:{}", JSON.toJSONString(device));
            log.info("开添加改产品物模型对设备对关联，产品code:{}-对设备code:{}",param.getProductId(),param.getCode());
            LambdaQueryWrapper<ProductProperty> ppWrapper=new LambdaQueryWrapper<>();
            ppWrapper.eq(ProductProperty::getProductId,param.getProductId());
            List<ProductProperty> propertyList=productPropertyMapper.selectList(ppWrapper);
            propertyList.stream().forEach(pp->{
                pp.setDeviceId(device.getId());
            });
            productPropertyMapper.insertOrUpdate(propertyList);
            log.info("新增设备完成～");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("新增失败!",e);
        }
    }

    /**
    * @Author Mr.Wang
    * @Description 修改设备信息
    * @Date 09:38 2025/9/29
    * @param code 设备编码
    * @param param 修改数据集
    **/
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public ResultData updateDevice(String code, UpdateDeviceParam param) {
        // 检查参数有效性
        if (StringUtils.isEmpty(code)) {
            return new ResultData("设备编码不能为空！");
        }
        try {
            Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
                    .eq(Device::getCode, code)
                    .select(Device::getId, Device::getDeleted));
            if (device == null) {
                return new ResultData("未找到编码为：" + code + " 的设备！");
            } else if (Objects.equals(device.getStatus(), DeviceStatusEnum.UN_AUTHENTICATED.getCode())) {
                return new ResultData("设备编码:" + code + "还未认证不能更改！");
            } else {
                List<ProductProperty> propertyList = param.getProperties();
                productPropertyMapper.insertOrUpdate(propertyList);
            }
            SqlTypeConverter.copyEntity(param, device);
            LambdaUpdateWrapper<Device> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Device::getCode, code);
            deviceMapper.update(device, updateWrapper);
        } catch (Exception e) {
            log.error("修改设备信息异常，产品编码：{}", code, e);
            throw new BusinessException("设备修改失败：{}", e);
        }
        return new ResultData("修改成功！");
    }

    /**
    * @Author Mr.Wang
    * @Description 设备认证
    * @Date 17:27 2025/9/28
    * @param code 设备编码
    * @param clientId 客户端ID
    * @param authPassword 认证密码
    **/
    @Override
    public ResultData certificationDevice(String code,String clientId,String authPassword) {
        //设备认证
        ResultData resultData=  mqttAuthService.authenticate(clientId,null,authPassword);
        if (resultData.getType().equals(BusinessCode.SUCCESS.name())) {
            Device device=deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
                    .eq(Device::getCode,code)
                    .select(Device::getId,Device::getDeleted));
            if (device == null) {
                return new ResultData("未找到编码为：" + code + " 的设备！");
            }else if (Objects.equals(device.getStatus(), DeviceStatusEnum.UN_AUTHENTICATED.getCode())){
                return  new ResultData("设备编码:"+code+"还未认证不能启用！");
            }
            LambdaUpdateWrapper<Device> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Device::getCode, code);
            device.setStatus(DeviceStatusEnum.AUTHENTICATED.getCode());
            deviceMapper.update(device,updateWrapper);
            log.info("设备认证成功！code:{}",code);
        }
        log.info("设备认证失败！");
        return resultData;
    }

    /**
    * @Author Mr.Wang
    * @Description 启用设备
    * @Date 10:37 2025/9/29
    * @param code 设备code
    * @param status 状态值
    **/
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public ResultData updateDeviceStatus(String code, Integer status) {
        // 检查参数有效性
        if (StringUtils.isEmpty(code)) {
            return new ResultData("设备编码不能为空！");
        }
        try {
            Device device=deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
                    .eq(Device::getCode,code)
                    .select(Device::getId,Device::getDeleted));
            if (device == null) {
                return new ResultData("未找到编码为：" + code + " 的设备！");
            }else if (Objects.equals(device.getStatus(), DeviceStatusEnum.UN_AUTHENTICATED.getCode())){
                return  new ResultData("设备编码:"+code+"还未认证不能启用！");
            }
            LambdaUpdateWrapper<Device> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Device::getCode, code);
            device.setStatus(status);
            deviceMapper.update(device,updateWrapper);
        } catch (Exception e) {
            log.error("修改设备状态异常，产品编码：{}", code, e);
            throw new BusinessException("设备状态修改失败：{}", e);
        }
        return new ResultData("修改成功！");
    }

    /**
    * @Author Mr.Wang
    * @Description 发送信息到设备
    * @Date 16:18 2025/9/29
    * @param topic
    **/
    @Override
    public ResultData deviceSendInfo(String topic, DeviceReceiveInfo messages) {
        try {
            // 这是真正的MQTT发送逻辑，通过MQTT网关发送消息到设备
            String payload = JSON.toJSONString(messages);
            mqttService.publish(topic, 1, payload); // 使用之前定义的MqttGateway

            return new ResultData("消息发送成功");
        } catch (Exception e) {
            throw new BusinessException("消息发送失败: ", e);
        }
    }

    @Override
    public ResultData receiveExternalMessage(String topic, DeviceReceiveInfo messages) {
        try {
            // 处理外部系统通过HTTP推送的消息（原deviceSendInfo的逻辑）
            messages.setReceiveTime(new Date()); // 添加接收时间
            mqttReceiver.getMessagesByTopic(topic).add(messages);

            // 同时通过WebSocket推送给前端（如果已实现WebSocket）
            if (webSocketTemplate != null) {
                Map<String, Object> pushData = new HashMap<>();
                pushData.put("topic", topic);
                pushData.put("message", messages);
                pushData.put("timestamp", System.currentTimeMillis());
                webSocketTemplate.convertAndSend("/topic/mqtt/" + topic, pushData);
            }
            return new ResultData("外部消息接收成功");
        } catch (Exception e) {
            throw new BusinessException("外部消息处理失败: ", e);
        }
    }

    /**
    * @Author Mr.Wang
    * @Description 接收信息
    * @Date 16:33 2025/9/29
    * @param
    **/
    @Override
    public ResultData getDeviceMessagesByTopic(String topic) {
        Map<String,Object> resultMap=new HashMap<>();
        List<DeviceReceiveInfo> receiveInfoList= mqttReceiver.getMessagesByTopic(topic);
        if (receiveInfoList.isEmpty()) {
            return null;
        }
        resultMap.put("messages",receiveInfoList);
        return new ResultData("获取设备发送信息！",resultMap);
    }
}